Project: Taiwan Referendum 2021
Kuo, Yao-Jen yaojenkuo@ntu.edu.tw from DATAINPOINT
# Importing libraries/functions the project needs
import os
import numpy as np
import pandas as pd
import folium
110 年公民投票全國性公投:https://www.cec.gov.tw/pc/zh_TW/index.html
We can use pd.read_excel for importing.
Check the list of worksheets before importing.
file_name = "data/表5-臺北市-全國性公民投票得票數一覽表(投開票所).xls"
excel_file = pd.ExcelFile(file_name)
print(excel_file.sheet_names)
['第17案', '第18案', '第19案', '第20案']
df = pd.read_excel(excel_file)
df.head()
| 110年全國性公民投票第17案在臺北市各投開票所得票數一覽表 | Unnamed: 1 | Unnamed: 2 | Unnamed: 3 | Unnamed: 4 | Unnamed: 5 | Unnamed: 6 | Unnamed: 7 | Unnamed: 8 | Unnamed: 9 | Unnamed: 10 | Unnamed: 11 | Unnamed: 12 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 鄉(鎮、市、區)別 | 村里別 | 投開票所別 | 得票情形 | NaN | A\n有效票數\nA=1+2 | B\n無效票數 | C\n投票數\nC=A+B | D\n已領未投票數\nD=E-C | E\n發出票數\nE=C+D | F\n用餘票數 | G\n投票權人數\nG=E+F | H\n投票率\nH=C÷G\n(%) |
| 1 | NaN | NaN | NaN | 1\n同意 | 2\n不同意 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 2 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 3 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 4 | 總 計 | NaN | NaN | 514232 | 490692 | 1004924 | 9609 | 1014533 | 192 | 1014725 | 1140691 | 2155416 | 47.07 |
sheet_name parameter¶for sheetName in excel_file.sheet_names:
df = pd.read_excel(file_name, sheet_name=sheetName)
print(f"Shape of {sheetName}: {df.shape}")
Shape of 第17案: (1762, 13) Shape of 第18案: (1762, 13) Shape of 第19案: (1762, 13) Shape of 第20案: (1762, 13)
sheet_name parameter can also accept integer as input¶for i in range(len(excel_file.sheet_names)):
df = pd.read_excel(file_name, sheet_name=i)
print(f"Shape of the {i}th sheet: {df.shape}")
Shape of the 0th sheet: (1762, 13) Shape of the 1th sheet: (1762, 13) Shape of the 2th sheet: (1762, 13) Shape of the 3th sheet: (1762, 13)
Tidy datasets are all alike, but every messy dataset is messy in its own way
There are three interrelated rules which make a dataset tidy:
- Each variable must have its own column.
- Each observation must have its own row.
- Each value must have its own cell.
Simply put, once our data is in tidy format, it is easy to use and quite convenient to tranform into the designated format of visualization or modeling functions for the next stage of data science project.
skiprows parameter to skip those combined cells while importing workbook¶df = pd.read_excel(file_name, skiprows=[0, 1, 3, 4])
df.head()
| Unnamed: 0 | Unnamed: 1 | Unnamed: 2 | 1\n同意 | 2\n不同意 | Unnamed: 5 | Unnamed: 6 | Unnamed: 7 | Unnamed: 8 | Unnamed: 9 | Unnamed: 10 | Unnamed: 11 | Unnamed: 12 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 總 計 | NaN | NaN | 514232 | 490692 | 1004924 | 9609 | 1014533 | 192 | 1014725 | 1140691 | 2155416 | 47.07 |
| 1 | 松山區 | NaN | NaN | 42583 | 37246 | 79829 | 743 | 80572 | 4 | 80576 | 82388 | 162964 | 49.44 |
| 2 | NaN | 莊敬里 | 1.0 | 285 | 251 | 536 | 1 | 537 | 0 | 537 | 537 | 1074 | 50.00 |
| 3 | NaN | 莊敬里 | 2.0 | 254 | 237 | 491 | 9 | 500 | 0 | 500 | 638 | 1138 | 43.94 |
| 4 | NaN | 莊敬里 | 3.0 | 228 | 198 | 426 | 5 | 431 | 0 | 431 | 652 | 1083 | 39.80 |
columns attributes with new column names and drop columns¶df = df.iloc[:, :5]
df.columns = ["town", "village", "office", "agree", "disagree"]
df.head()
| town | village | office | agree | disagree | |
|---|---|---|---|---|---|
| 0 | 總 計 | NaN | NaN | 514232 | 490692 |
| 1 | 松山區 | NaN | NaN | 42583 | 37246 |
| 2 | NaN | 莊敬里 | 1.0 | 285 | 251 |
| 3 | NaN | 莊敬里 | 2.0 | 254 | 237 |
| 4 | NaN | 莊敬里 | 3.0 | 228 | 198 |
fillna() to forward-fill town values¶ffill: propagate last valid observation forward to next valid.
filled_towns = df["town"].fillna(method='ffill')
df = df.assign(town=filled_towns)
df.head()
| town | village | office | agree | disagree | |
|---|---|---|---|---|---|
| 0 | 總 計 | NaN | NaN | 514232 | 490692 |
| 1 | 松山區 | NaN | NaN | 42583 | 37246 |
| 2 | 松山區 | 莊敬里 | 1.0 | 285 | 251 |
| 3 | 松山區 | 莊敬里 | 2.0 | 254 | 237 |
| 4 | 松山區 | 莊敬里 | 3.0 | 228 | 198 |
dropna()¶df = df.dropna()
df.head()
| town | village | office | agree | disagree | |
|---|---|---|---|---|---|
| 2 | 松山區 | 莊敬里 | 1.0 | 285 | 251 |
| 3 | 松山區 | 莊敬里 | 2.0 | 254 | 237 |
| 4 | 松山區 | 莊敬里 | 3.0 | 228 | 198 |
| 5 | 松山區 | 莊敬里 | 4.0 | 310 | 251 |
| 6 | 松山區 | 東榮里 | 5.0 | 333 | 337 |
town via str.replace()¶print(df['town'].unique())
stripped_town = df['town'].str.strip()
df = df.assign(town=stripped_town)
print(df['town'].unique())
[' 松山區' ' 信義區' ' 大安區' ' 中山區' ' 中正區' ' 大同區' ' 萬華區' ' 文山區' ' 南港區' ' 內湖區' ' 士林區' ' 北投區'] ['松山區' '信義區' '大安區' '中山區' '中正區' '大同區' '萬華區' '文山區' '南港區' '內湖區' '士林區' '北投區']
df_long = pd.melt(df, id_vars=["town", "village", "office"],
var_name='variable',
value_name='votes'
)
df_long.head()
| town | village | office | variable | votes | |
|---|---|---|---|---|---|
| 0 | 松山區 | 莊敬里 | 1.0 | agree | 285 |
| 1 | 松山區 | 莊敬里 | 2.0 | agree | 254 |
| 2 | 松山區 | 莊敬里 | 3.0 | agree | 228 |
| 3 | 松山區 | 莊敬里 | 4.0 | agree | 310 |
| 4 | 松山區 | 東榮里 | 5.0 | agree | 333 |
df_long = df_long.astype({"office": int})
df_long.dtypes
town object village object office int64 variable object votes int64 dtype: object
melt_tidy_dataframe() which assembles the previous cells¶def melt_tidy_dataframe(df):
# updating columns attributes
df = df.iloc[:, :5]
df.columns = ["town", "village", "office", "agree", "disagree"]
# forward-fill town values
filled_towns = df['town'].fillna(method='ffill')
df = df.assign(town=filled_towns)
# removing subtotals and totals
df = df.dropna()
# removing extra spaces
stripped_town = df['town'].str.strip()
df = df.assign(town=stripped_town)
# transposing
df_long = pd.melt(df, id_vars=["town", "village", "office"],
var_name='variable',
value_name='votes'
)
# adjusting data type
df_long = df_long.astype({"office": int})
return df_long
list_dir = os.listdir("data")
file_names = [file for file in list_dir if ".xls" in file and ".xlsx" not in file]
print(file_names)
['表5-臺東縣-全國性公民投票得票數一覽表(投開票所).xls', '表5-基隆市-全國性公民投票得票數一覽表(投開票所).xls', '表5-雲林縣-全國性公民投票得票數一覽表(投開票所).xls', '表5-嘉義市-全國性公民投票得票數一覽表(投開票所).xls', '表5-新竹縣-全國性公民投票得票數一覽表(投開票所).xls', '表5-澎湖縣-全國性公民投票得票數一覽表(投開票所).xls', '表5-金門縣-全國性公民投票得票數一覽表(投開票所).xls', '表5-嘉義縣-全國性公民投票得票數一覽表(投開票所).xls', '表5-高雄市-全國性公民投票得票數一覽表(投開票所).xls', '表5-新竹市-全國性公民投票得票數一覽表(投開票所).xls', '表5-花蓮縣-全國性公民投票得票數一覽表(投開票所).xls', '表5-南投縣-全國性公民投票得票數一覽表(投開票所).xls', '表5-臺北市-全國性公民投票得票數一覽表(投開票所).xls', '表5-苗栗縣-全國性公民投票得票數一覽表(投開票所).xls', '表5-桃園市-全國性公民投票得票數一覽表(投開票所).xls', '表5-宜蘭縣-全國性公民投票得票數一覽表(投開票所).xls', '表5-臺南市-全國性公民投票得票數一覽表(投開票所).xls', '表5-新北市-全國性公民投票得票數一覽表(投開票所).xls', '表5-臺中市-全國性公民投票得票數一覽表(投開票所).xls', '表5-連江縣-全國性公民投票得票數一覽表(投開票所).xls', '表5-彰化縣-全國性公民投票得票數一覽表(投開票所).xls', '表5-屏東縣-全國性公民投票得票數一覽表(投開票所).xls']
melt_tidy_dataframe() on all workbooks¶sheet_order_case_number = {i: i+17 for i in range(4)}
print(sheet_order_case_number)
{0: 17, 1: 18, 2: 19, 3: 20}
appended_df = pd.DataFrame()
for file_name in file_names:
county = file_name.split("-")[1]
for key, value in sheet_order_case_number.items():
df = pd.read_excel(f"data/{file_name}", skiprows=[0, 1, 3, 4], sheet_name=key)
melted_tidy_dataframe = melt_tidy_dataframe(df)
melted_tidy_dataframe['county'] = county
melted_tidy_dataframe['case'] = value
appended_df = appended_df.append(melted_tidy_dataframe)
print(f"Melting and tidying worksheet {key} of {file_name}...")
appended_df = appended_df.reset_index(drop=True) # reset index for the appended dataframe
Melting and tidying worksheet 0 of 表5-臺東縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-臺東縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-臺東縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-臺東縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-基隆市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-基隆市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-基隆市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-基隆市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-雲林縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-雲林縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-雲林縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-雲林縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-嘉義市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-嘉義市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-嘉義市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-嘉義市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-新竹縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-新竹縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-新竹縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-新竹縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-澎湖縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-澎湖縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-澎湖縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-澎湖縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-金門縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-金門縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-金門縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-金門縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-嘉義縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-嘉義縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-嘉義縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-嘉義縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-高雄市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-高雄市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-高雄市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-高雄市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-新竹市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-新竹市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-新竹市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-新竹市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-花蓮縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-花蓮縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-花蓮縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-花蓮縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-南投縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-南投縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-南投縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-南投縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-臺北市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-臺北市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-臺北市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-臺北市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-苗栗縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-苗栗縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-苗栗縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-苗栗縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-桃園市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-桃園市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-桃園市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-桃園市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-宜蘭縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-宜蘭縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-宜蘭縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-宜蘭縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-臺南市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-臺南市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-臺南市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-臺南市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-新北市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-新北市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-新北市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-新北市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-臺中市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-臺中市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-臺中市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-臺中市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-連江縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-連江縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-連江縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-連江縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-彰化縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-彰化縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-彰化縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-彰化縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-屏東縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-屏東縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-屏東縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-屏東縣-全國性公民投票得票數一覽表(投開票所).xls...
appended_df.head()
| town | village | office | variable | votes | county | case | |
|---|---|---|---|---|---|---|---|
| 0 | 臺東市 | 文化里 | 1 | agree | 138 | 臺東縣 | 17 |
| 1 | 臺東市 | 民族里 | 2 | agree | 102 | 臺東縣 | 17 |
| 2 | 臺東市 | 民族里 | 3 | agree | 161 | 臺東縣 | 17 |
| 3 | 臺東市 | 自強里 | 4 | agree | 236 | 臺東縣 | 17 |
| 4 | 臺東市 | 自強里 | 5 | agree | 248 | 臺東縣 | 17 |
appended_df.tail()
| town | village | office | variable | votes | county | case | |
|---|---|---|---|---|---|---|---|
| 139827 | 牡丹鄉 | 牡丹村 | 708 | disagree | 28 | 屏東縣 | 20 |
| 139828 | 牡丹鄉 | 東源村 | 709 | disagree | 25 | 屏東縣 | 20 |
| 139829 | 牡丹鄉 | 旭海村 | 710 | disagree | 30 | 屏東縣 | 20 |
| 139830 | 牡丹鄉 | 高士村 | 711 | disagree | 29 | 屏東縣 | 20 |
| 139831 | 牡丹鄉 | 四林村 | 712 | disagree | 22 | 屏東縣 | 20 |
TaiwanReferendum2021 to make the above codes more organized¶class TaiwanRefendum2021:
def __init__(self):
self.sheet_order_case_number = {i: i+17 for i in range(4)}
self.file_names = [file for file in os.listdir("data") if ".xls" in file and ".xlsx" not in file]
def melt_tidy_dataframe(self, df):
# updating columns attributes
df = df.iloc[:, :5]
df.columns = ["town", "village", "office", "agree", "disagree"]
# forward-fill town values
filled_towns = df['town'].fillna(method='ffill')
df = df.assign(town=filled_towns)
# removing subtotals and totals
df = df.dropna()
# removing extra spaces
stripped_town = df['town'].str.strip()
df = df.assign(town=stripped_town)
# transposing
df_long = pd.melt(df, id_vars=["town", "village", "office"],
var_name='variable',
value_name='votes'
)
# adjusting data type
df_long = df_long.astype({"office": int})
return df_long
def create_referendum_dataframe(self):
appended_df = pd.DataFrame()
for file_name in self.file_names:
county = file_name.split("-")[1]
for key, value in self.sheet_order_case_number.items():
df = pd.read_excel(f"data/{file_name}", skiprows=[0, 1, 3, 4], sheet_name=key)
melted_tidy_dataframe = self.melt_tidy_dataframe(df)
melted_tidy_dataframe['county'] = county
melted_tidy_dataframe['case'] = value
appended_df = appended_df.append(melted_tidy_dataframe)
print(f"Melting and tidying worksheet {key} of {file_name}...")
appended_df = appended_df.reset_index(drop=True) # reset index for the appended dataframe
out_df = appended_df[["county", "town", "village", "office", "case", "variable", "votes"]]
return out_df
TaiwanReferendum2021 class to generate the compact DataFrame¶taiwan_referendum_2021 = TaiwanRefendum2021()
referendum_dataframe = taiwan_referendum_2021.create_referendum_dataframe()
Melting and tidying worksheet 0 of 表5-臺東縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-臺東縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-臺東縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-臺東縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-基隆市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-基隆市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-基隆市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-基隆市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-雲林縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-雲林縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-雲林縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-雲林縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-嘉義市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-嘉義市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-嘉義市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-嘉義市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-新竹縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-新竹縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-新竹縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-新竹縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-澎湖縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-澎湖縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-澎湖縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-澎湖縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-金門縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-金門縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-金門縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-金門縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-嘉義縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-嘉義縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-嘉義縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-嘉義縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-高雄市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-高雄市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-高雄市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-高雄市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-新竹市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-新竹市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-新竹市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-新竹市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-花蓮縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-花蓮縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-花蓮縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-花蓮縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-南投縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-南投縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-南投縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-南投縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-臺北市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-臺北市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-臺北市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-臺北市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-苗栗縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-苗栗縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-苗栗縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-苗栗縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-桃園市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-桃園市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-桃園市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-桃園市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-宜蘭縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-宜蘭縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-宜蘭縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-宜蘭縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-臺南市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-臺南市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-臺南市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-臺南市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-新北市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-新北市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-新北市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-新北市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-臺中市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-臺中市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-臺中市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-臺中市-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-連江縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-連江縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-連江縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-連江縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-彰化縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-彰化縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-彰化縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-彰化縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 0 of 表5-屏東縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 1 of 表5-屏東縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 2 of 表5-屏東縣-全國性公民投票得票數一覽表(投開票所).xls... Melting and tidying worksheet 3 of 表5-屏東縣-全國性公民投票得票數一覽表(投開票所).xls...
referendum_dataframe
| county | town | village | office | case | variable | votes | |
|---|---|---|---|---|---|---|---|
| 0 | 臺東縣 | 臺東市 | 文化里 | 1 | 17 | agree | 138 |
| 1 | 臺東縣 | 臺東市 | 民族里 | 2 | 17 | agree | 102 |
| 2 | 臺東縣 | 臺東市 | 民族里 | 3 | 17 | agree | 161 |
| 3 | 臺東縣 | 臺東市 | 自強里 | 4 | 17 | agree | 236 |
| 4 | 臺東縣 | 臺東市 | 自強里 | 5 | 17 | agree | 248 |
| ... | ... | ... | ... | ... | ... | ... | ... |
| 139827 | 屏東縣 | 牡丹鄉 | 牡丹村 | 708 | 20 | disagree | 28 |
| 139828 | 屏東縣 | 牡丹鄉 | 東源村 | 709 | 20 | disagree | 25 |
| 139829 | 屏東縣 | 牡丹鄉 | 旭海村 | 710 | 20 | disagree | 30 |
| 139830 | 屏東縣 | 牡丹鄉 | 高士村 | 711 | 20 | disagree | 29 |
| 139831 | 屏東縣 | 牡丹鄉 | 四林村 | 712 | 20 | disagree | 22 |
139832 rows × 7 columns
votes_by_village = referendum_dataframe.groupby(["county", "case", "variable"])["votes"].sum()
votes_by_village = pd.DataFrame(votes_by_village).reset_index()
votes_by_village
| county | case | variable | votes | |
|---|---|---|---|---|
| 0 | 南投縣 | 17 | agree | 82471 |
| 1 | 南投縣 | 17 | disagree | 73365 |
| 2 | 南投縣 | 18 | agree | 84903 |
| 3 | 南投縣 | 18 | disagree | 70911 |
| 4 | 南投縣 | 19 | agree | 84360 |
| ... | ... | ... | ... | ... |
| 171 | 高雄市 | 18 | disagree | 588302 |
| 172 | 高雄市 | 19 | agree | 398161 |
| 173 | 高雄市 | 19 | disagree | 588679 |
| 174 | 高雄市 | 20 | agree | 392910 |
| 175 | 高雄市 | 20 | disagree | 593239 |
176 rows × 4 columns
total_votes_by_village = referendum_dataframe.groupby(["county", "case"])["votes"].sum()
total_votes_by_village = pd.DataFrame(total_votes_by_village).reset_index()
total_votes_by_village
| county | case | votes | |
|---|---|---|---|
| 0 | 南投縣 | 17 | 155836 |
| 1 | 南投縣 | 18 | 155814 |
| 2 | 南投縣 | 19 | 155893 |
| 3 | 南投縣 | 20 | 155785 |
| 4 | 嘉義市 | 17 | 92209 |
| ... | ... | ... | ... |
| 83 | 雲林縣 | 20 | 201035 |
| 84 | 高雄市 | 17 | 986618 |
| 85 | 高雄市 | 18 | 986292 |
| 86 | 高雄市 | 19 | 986840 |
| 87 | 高雄市 | 20 | 986149 |
88 rows × 3 columns
merged_df = pd.merge(votes_by_village, total_votes_by_village,
left_on=["county", "case"],
right_on=["county", "case"])
percentages = merged_df["votes_x"] / merged_df["votes_y"]
percentage_df = pd.DataFrame()
percentage_df["county"] = merged_df["county"].values
percentage_df["case"] = merged_df["case"].values
percentage_df["variable"] = merged_df["variable"].values
percentage_df["percentage"] = percentages
percentage_df
| county | case | variable | percentage | |
|---|---|---|---|---|
| 0 | 南投縣 | 17 | agree | 0.529217 |
| 1 | 南投縣 | 17 | disagree | 0.470783 |
| 2 | 南投縣 | 18 | agree | 0.544900 |
| 3 | 南投縣 | 18 | disagree | 0.455100 |
| 4 | 南投縣 | 19 | agree | 0.541140 |
| ... | ... | ... | ... | ... |
| 171 | 高雄市 | 18 | disagree | 0.596479 |
| 172 | 高雄市 | 19 | agree | 0.403471 |
| 173 | 高雄市 | 19 | disagree | 0.596529 |
| 174 | 高雄市 | 20 | agree | 0.398429 |
| 175 | 高雄市 | 20 | disagree | 0.601571 |
176 rows × 4 columns
counties = percentage_df["county"].map(lambda x: x.replace("臺", "台"))
counties = counties.map(lambda x: x.replace("桃園市", "桃園縣"))
percentage_viz = pd.DataFrame()
percentage_viz["county"] = counties.values
percentage_viz["case"] = percentage_df["case"].values
percentage_viz["variable"] = percentage_df["variable"].values
percentage_viz["percentage"] = np.round(percentage_df["percentage"].values * 100, 2)
percentage_viz
| county | case | variable | percentage | |
|---|---|---|---|---|
| 0 | 南投縣 | 17 | agree | 52.92 |
| 1 | 南投縣 | 17 | disagree | 47.08 |
| 2 | 南投縣 | 18 | agree | 54.49 |
| 3 | 南投縣 | 18 | disagree | 45.51 |
| 4 | 南投縣 | 19 | agree | 54.11 |
| ... | ... | ... | ... | ... |
| 171 | 高雄市 | 18 | disagree | 59.65 |
| 172 | 高雄市 | 19 | agree | 40.35 |
| 173 | 高雄市 | 19 | disagree | 59.65 |
| 174 | 高雄市 | 20 | agree | 39.84 |
| 175 | 高雄市 | 20 | disagree | 60.16 |
176 rows × 4 columns
def show_percentage_on_map(case_num, variable):
village_geo = "https://raw.githubusercontent.com/g0v/twgeojson/master/json/twCounty2010.geo.json"
m = folium.Map(location=[24, 123], zoom_start=7)
if variable == "agree":
color_brewer = "Blues"
else:
color_brewer = "Greens"
folium.Choropleth(
geo_data=village_geo,
name="choropleth",
data=percentage_viz[(percentage_viz["case"] == case_num) & (percentage_viz["variable"] == variable)],
columns=["county", "percentage"],
key_on="feature.properties.COUNTYNAME",
fill_color=color_brewer,
fill_opacity=0.7,
line_opacity=0.2,
legend_name=f"Case{case_num} {variable} Percentage (%)",
).add_to(m)
folium.LayerControl().add_to(m)
return m
m = show_percentage_on_map(17, "disagree")
m